<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Java基础 | 王开琦的个人小站</title><meta name="author" content="王开琦"><meta name="copyright" content="王开琦"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="为什么 Java 代码可以实现一次编写、到处运行？ 查看答案     参考答案 JVM（ Java 虚拟机）是 Java 跨平台的关键。 在程序运行前，Java 源代码（.java）需要经过编译器编译成字节码（.class）。在程序运行时，JVM负责将字节码翻译成特定平台下的机器码并运行，也就是说，只要在不同的平台上安装对应的JVM，就可以运行字节码文件。 同一份Java源代码在不同的平台上运行">
<meta property="og:type" content="article">
<meta property="og:title" content="Java基础">
<meta property="og:url" content="https://blog.wkq.pub/blog/1-Java-Java%E5%9F%BA%E7%A1%80/index.html">
<meta property="og:site_name" content="王开琦的个人小站">
<meta property="og:description" content="为什么 Java 代码可以实现一次编写、到处运行？ 查看答案     参考答案 JVM（ Java 虚拟机）是 Java 跨平台的关键。 在程序运行前，Java 源代码（.java）需要经过编译器编译成字节码（.class）。在程序运行时，JVM负责将字节码翻译成特定平台下的机器码并运行，也就是说，只要在不同的平台上安装对应的JVM，就可以运行字节码文件。 同一份Java源代码在不同的平台上运行">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://blog.wkq.pub/cover/Java.png">
<meta property="article:published_time" content="2021-09-21T07:13:20.000Z">
<meta property="article:modified_time" content="2021-12-07T10:21:22.000Z">
<meta property="article:author" content="王开琦">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://blog.wkq.pub/cover/Java.png"><link rel="shortcut icon" href="/media/favicon.ico"><link rel="canonical" href="https://blog.wkq.pub/blog/1-Java-Java%E5%9F%BA%E7%A1%80/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: true,
  islazyload: true,
  isanchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'Java基础',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: false,
  postUpdate: '2021-12-07 18:21:22'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if (GLOBAL_CONFIG_SITE.isHome && /iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    document.addEventListener('pjax:complete', detectApple)})(window)</script><meta name="generator" content="Hexo 5.2.0"></head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="/media/avatar.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">15</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">17</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">分类</div><div class="length-num">15</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('/cover/Java.png')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">王开琦的个人小站</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">Java基础</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-09-21T07:13:20.000Z" title="发表于 2021-09-21 15:13:20">2021-09-21</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2021-12-07T10:21:22.000Z" title="更新于 2021-12-07 18:21:22">2021-12-07</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Java/">Java</a><i class="fas fa-angle-right post-meta-separator"></i><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Java/%E5%9F%BA%E7%A1%80/">基础</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">8.6k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>26分钟</span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><ol>
<li><p>为什么 Java 代码可以实现一次编写、到处运行？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>JVM（ Java 虚拟机）是 Java 跨平台的关键。</p>
<p>在程序运行前，Java 源代码（.java）需要经过编译器编译成字节码（.class）。在程序运行时，JVM负责将字节码翻译成特定平台下的机器码并运行，也就是说，只要在不同的平台上安装对应的JVM，就可以运行字节码文件。</p>
<p>同一份Java源代码在不同的平台上运行，它不需要做任何的改变，并且只需要编译一次。编译好的字节码，是通过 JVM 这个中间的“桥梁”实现跨平台的，JVM 是与平台无关的软件，它能将统一的字节码翻译成该平台的机器码。</p>
<p><strong>注意事项</strong></p>
<ol>
<li>编译的结果是生成字节码、不是机器码，字节码不能直接运行，必须通过 JVM 翻译成机器码才能运行；</li>
<li>跨平台的是Java程序、而不是 JVM ，不同平台需要安装不同版本的 JVM。</li>
</ol>
</div></div>
</li>
<li><p>一个 Java 文件里可以有多个类吗（不含内部类）？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<ol>
<li>一个 java 文件里可以有多个类，但最多只能有一个被 public 修饰的类；</li>
<li>如果这个 java 文件中包含 public 修饰的类，则这个类的名称必须和 java 文件名一致</li>
</ol>
</div></div>
</li>
<li><p>说一说你对Java访问权限的了解？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>Java 语言提供了三种访问修饰符，即 private、protected、public，在使用这些修饰符修饰目标时，一共可以形成四种访问权限，即 private 、 default 、protected 、public ，不加任何修饰符的时候为 default 访问权限。</p>
<p>在修饰成员变量/成员方法时，该成员的四种访问权限的含义如下：</p>
<ul>
<li>private ：该成员可以被该类内部成员访问；包括内部类</li>
<li>default  ： 该成员可以被该类内部成员访问，也可以被同一包下其它的类访问；</li>
<li>protected ： 该成员可以被该类内部成员访问，也可以被同一包下其它的类访问，还可以被它的子类访问；</li>
<li>public ： 该成员可以被任意包下，任意类的成员进行访问；</li>
</ul>
<p>在修饰类时，该类只有两种访问权限，对应的访问权限含义如下：</p>
<ul>
<li>default ：该类可以被同一包下其他类访问；</li>
<li>public ：该类可以被任意包下，任意的类所访问；</li>
</ul>
</div></div>
</li>
<li><p>Java 的数据类型</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>Java 数据类型包括基本数据类型和引用数据类型两大类。</p>
<p>基本数据类型有8个，可以分为4个小类，分别是整数类型（byte/short/int/long）、浮点类型（float/double）、字符类型（char）、布尔类型（boolean） 。其中，4个整数类型中，int 类型最为常用。2个浮点数类型中，double 最为常用。另外，在这8 个基本类型当中，除了布尔类型之外的其它7个类型，都可以看作是数字类型，它们相互之间可以进行类型转换。</p>
<p>引用类型是对一个对象的引用，根据引用类型的不同，可以将引用类型分为3类，即数组、类、接口类型。引用类型本质上是通过指针，指向堆中对象所持有的内存空间，只是 Java 语言不在沿用指针这个说法而已。</p>
<ul>
<li>byte ： 1字节（8位）</li>
<li>short : 2字节 （16位）</li>
<li>int ： 4字节 (32位)</li>
<li>long ： 8字节（64位）</li>
<li>float ： 4字节（32位）</li>
<li>double ： 8字节（64位）</li>
<li>char ： 2字节（16位）</li>
<li>boolean： Java 规范没有明确的规定，不同的 JVM 有不同的实现机制</li>
</ul>
</div></div>
</li>
<li><p>请介绍全局变量和局部变量的区别？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>Java 中的变量分为成员变量和全局变量，它们的区别如下：</p>
<p>成员变量：</p>
<ol>
<li>成员变量是在类的范围内定义的变量；</li>
<li>成员变量有默认初始值；</li>
<li>未被 static 修饰的成员变量也叫做实例变量，它存储于对象所在的堆内存中，生命周期与对象相同；</li>
<li>被static修饰的成员变量也叫做类变量，它存储于方法区中，生命周期与当前类相同；</li>
</ol>
<p>局部变量： </p>
<ol>
<li>局部变量是在方法里定义的变量；</li>
<li>局部变量没有默认初始值；</li>
<li>局部变量存储于栈内存中，作用的范围结束，变量空间会自动的释放；</li>
</ol>
</div></div>
</li>
<li><p>请介绍一下实例变量的默认值</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>实例变量若为引用数据类型，其默认值一律为 null 。若为基本数据类型，其默认值如下：</p>
<ul>
<li>byte /short/int: 0</li>
<li>long : 0L</li>
<li>float : 0.0F</li>
<li>double :   0.0</li>
<li>char : ‘\u0000’</li>
<li>boolean :  false</li>
</ul>
<p><strong>注意事项</strong></p>
<p>上述规则适用于所有的成员变量，所以对于类变量也是适用的。</p>
</div></div>
</li>
<li><p>包装类和自动装箱、自动拆箱的应用场景</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>Java 为每个基本数据类型都定义了一个对应的引用类型，这就是包装类。</p>
<p>自动装箱是 JDK1.5提供了功能。</p>
<p>自动装箱： 可以把一个基本数据类型的数据直接赋值给对应的包装类型；</p>
<p>自动拆箱： 可以把一个包装类型的对象直接赋值给对应的基本类型；</p>
<p>通过自动装箱、自动拆箱功能，可以大大简化基本类型变量和包装类对象之间的转换过程。</p>
</div></div>
</li>
<li><p>如何对 Integer 和 Double 类型判断相等？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>Integer 、 Double 不能直接进行比较，这包括：</p>
<ul>
<li>不能用 == 进行直接，因为它们是不同的数据类型；</li>
<li>不能转为字符串进行比较，因为转为字符串后，浮点值带小数，整数值不带，这样它们永远不会相等；</li>
<li>不能使用 compareTo 方法进行比较，虽然它们都有 compareTo 方法，但该方法只能对相同类型进行比较</li>
</ul>
<p>整数、浮点类型的包装类，都继承于 Number 类型，而 Number 类型分别定义了将数字转换为 byte、short、 int 、 long、 float、double的方法，所以可以将 Integer、Double 先转换为相同的基本数据类型（如double），然后使用 == 进行比较。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Integer i=<span class="number">100</span>;</span><br><span class="line">Double d=<span class="number">100.00</span>;</span><br><span class="line">System.out.println(i.doubleValue()==d.doubleValue());</span><br></pre></td></tr></table></figure>
</div></div>
</li>
<li><p>int 和 Integer 有什么区别，二者在做 == 运算时会得到什么结果？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>int 是 基本数据类型，Integer 是 int 的包装类。二者在做 == 运算时， Integer 会自动拆箱为 int  类型，然后再进行比较。届时，如果两个 int  值相等则返回 true  ，否则就返回 false。</p>
</div></div>
</li>
<li><p>面向对象的三大特征是什么？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>封装： 将对象的实现细节隐藏起来，通过一些公用方法来暴露该对象的功能；</p>
<p>继承：面向对象实现软件复用的重要手段，当子类继承父类后，子类作为一个特殊的父类，将直接获得父类的属性和方法（private不能）；</p>
<p>多态：多态是指子类对象可以直接赋给父类变量，但运行时依然表现出子类的行为特征，这意味着同一个类型的对象在执行同一个方法时，可能表现出多种行为特征。</p>
</div></div>
</li>
<li><p>封装的目的是什么？为什么要有封装？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>封装是面向对象编程语言对客观世界的模拟，在客观世界里，对象的状态信息都被隐藏在对象内部，外部无法直接操作或修改。对一个类或对象实现良好的封装，可以实现以下目的：</p>
<ol>
<li>隐藏类的实现细节；</li>
<li>让使用者只能通过实现预定的方法来访问数据，从而可以在该方法里加入控制逻辑，限制对成员变量的不合理访问；</li>
<li>可进行数据检查，从而有利于保证对象信息的完整性；</li>
<li>便于修改，提高代码的可维护性；</li>
</ol>
<p><strong>注意</strong></p>
<p>​    实现良好的封装，需要从两个方面考虑：</p>
<ul>
<li>将对象的成员变量和实现细节隐藏起来，不允许外部直接访问；</li>
<li>把方法暴露出来，让方法来控制这些成员进行安全的访问。</li>
</ul>
</div></div>
</li>
<li><p>说一说你对多态的理解？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>因为子类是一种特殊的父类，因此Java允许把一个子类对象直接赋给一个父类引用变量，无须任何类型转换，或者称为向上转型，向上转型由系统自动完成。</p>
<p>当把一个子类对象直接赋给父类引用变量时，例如 BaseClass obj = new SubClass();这个 obj  引用变量 的编译时类型时 BaseClass ，而运行时类型是 SubClass，当运行时调用该引用变量的方法时，其方法行为总是表现出子类方法的行为特征，而不是父类方法的行为特征，这就可能出现：相同类型的变量，调用同一个方法时呈现出多种不同的行为特征，这就是多态。</p>
</div></div>
</li>
<li><p>Java中的多态是怎么实现的？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>多态的实现离不开继承，在设计程序时，我们可以将参数的类型定义为父类型。在调用程序时，则可以根据实际情况，传入该父类型的某个子类型的实例，这样就实现了多态。对于父类型，可以有三种形式，即普通的类、抽象类、接口。对于子类型，这要根据它自身的特征，重写父类的某些方法，或实现抽象类/接口的某些抽象方法。</p>
</div></div>
</li>
<li><p>Java 为什么是单继承，为什么不能多继承？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>首先，Java是单继承的，指的是Java中一个类只能有一个直接的父类。Java不能多继承，则是说Java中一个类不能直接继承多个父类。</p>
<p>Java语言之所以摒弃多继承的这项特性，是因为多继承容易产生混淆。比如，两个父类中包含相同的方法时，子类在调用该方法或重写该方法时就会迷惑。</p>
</div></div>
</li>
<li><p>说一说重写和重载的区别</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>重载发生在同一个类中，若多个方法之间方法名相同、参数列表不同，则它们构成重载的关系。重载与方法的返回值和访问修饰符无关。</p>
<p>重写发生在父类子类中，若子类要重写父类方法，则它的方法名和参数列表必须和父类方法相同，返回值类型必须小于等于父类方法，抛出的异常必须小于等于父类方法，访问修饰符必须大于等于父类方法。</p>
</div></div>
</li>
<li><p>构造方法能不能重写？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>构造方法不能重写，因为构造方法需要和类保持同名，而重写的要求是子类方法和父类方法保持同名。如果允许重写构造方法的话，那么子类中将会存在与类名不同的构造方法，这与构造方法的要求是矛盾的。</p>
</div></div>
</li>
<li><p>介绍一下 Object 类中的方法</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<ul>
<li>Class&lt;?&gt; getClass() : 返回该对象的运行时类。</li>
<li>boolean equals(Object obj ): 判断指定对象与该对象是否相等。</li>
<li>int hasCode（）：返回该对象的 hashCode值。在默认情况下，Object类的hashCode() 方法根据该对象的地址来计算。</li>
<li>String toString() ： 返回该对象的字符串表示，Object类的toString()方法返回 运行时类名@十六进制hashCode值 格式的字符串，</li>
<li>wait()、notify（）、notifyAll() ： 通过这几个方法可以控制线程的暂停和运行</li>
<li>clone（）： 帮助其它对象实现 自我克隆，由于该方法使用了 protected 修饰，因此它只能被子类重写或调用。</li>
<li>finalize（）方法：当系统中没有引用变量引用到该对象时，垃圾回收器调用此方法来清理该对象的资源。并且，针对某一个对象，垃圾回收器最多只会调用它的finalize（）方法一次。</li>
</ul>
</div></div>
</li>
<li><p>说一说 hashCode()  和 equals() 的关系</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>hashCode() 用于获取哈希码（散列码），equals（）用于比较两个对象是否相等，它们应遵守如下规定：</p>
<ul>
<li>如果两个对象相等，则它们必须有相同的哈希码。</li>
<li>如果两个对象有相同的哈希码，则它们未必相等。</li>
</ul>
<p>在 Java  中，Set接口是无序的，元素不可重复的集合，HashSet 则是 Set  接口的典型实现。</p>
<p>当向HashSet中加一个元素时，它需要判断集合中是否已经包含了这个元素，从而避免重复存储。由于这个判断十分的频繁，所以要讲求效率，绝不能采用遍历集合的逐个元素进行比较的方式。实际上，HashSet是通过获取对象的哈希码，以及调用对象的eqals()方法来解决这个问题的。</p>
<p>HashSet首先会调用对象的 hashCode () 方法获取其哈希码，并通过哈希码确定该对象在集合中存放的位置。假设这个位置之前已经存了一个对象，则HashSet会调用equals()对两个对象进行比较。若相等规则说明对象重复，此时不会保存新对象。若不等说明对象不重复，但是它们存储的位置发生了碰撞，此时HashSet会采用链式结构在同一个位置保存多个对象，即将新加对象链接到原来对象的之后。之后，再有新加对象也映射到这个位置时，就需要与这个位置中所有的对象进行 equals() 比较 ,若不相等则将其连接到最后一个对象之后。</p>
</div></div>
</li>
<li><p>为什么要重写 hashCode() 和 equals() ?</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>Object类提供的equals()方法默认是用 == 来进行比较的，也就是说只有两个对象是同一个对象时，才能返回相等的结果。而实际的业务中，我们通常的需求是，若两个不同的对象它们的内容是相同的，就认为它们是相同的。鉴于这种情况，Object类中equals()方法的默认实现是没有实用价值的，所以通常都要重写。</p>
<p>由于 hashCode() 与 equals () 具有联动关系，所以 equals() 方法重写时，通常也要将 hashCode() 进行重写，使得这两个方法始终满足相关的约定</p>
</div></div>
</li>
<li><p>==和equals()有什么区别？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>== 运算符：</p>
<ul>
<li>作用于基本数据类型时，是比较两个数值是否相等；</li>
<li>作用于引用数据类型时，是比较两个对象的内存地址是否相等，即判断它们是否是同一个对象；</li>
</ul>
<p>equals()方法：</p>
<ul>
<li>没有重写时，Object 默认以 == 来实现，即比较两个对象的内存地址是否相等；</li>
<li>进行重写后，按照重写的规则进行比较</li>
</ul>
</div></div>
</li>
<li><p>String 类有那些方法？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<ul>
<li>char charAt(int index)：返回指定索引处的字符；</li>
<li>String substring(int beginIndex,int endIndex)：从字符串中截取出一部分字符串；</li>
<li>String[] split(String regex)：以指定的规格将此字符串分割为数组；</li>
<li>String trim() ：删除字符串前后的空格</li>
<li>int indexOf(String str)：返回子串在此字符串首次出现的索引</li>
<li>int lastIndexOf(String str)：返回子串在此字符串最后出现的索引</li>
<li>boolean startWith(String prefix)：判断此字符串是否以指定的前缀开头；</li>
<li>boolean endWith(String suffix)：判断此字符串是否以指定的后缀结尾；</li>
<li>String toUpperCase()：将此字符串中所有的字符大写</li>
<li>String toLowerCase()： 将此字符串中所有字符小写</li>
<li>String replaceFirst(String regex,String replacement)：用指定字符串替换第一个匹配的子串</li>
<li>String replaceAll(String regex,String replacement)： 用指定字符串替换所有的匹配的子串</li>
</ul>
</div></div>
</li>
<li><p>String 可以被继承吗？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>String类由final修饰，所以不能被继承。</p>
<p>在Java中，String类被设计为不可变类，主要表现在它保存字符串的成员变量是final的。</p>
<ul>
<li>Java 9 之前字符串采用 char[]数组来保存字符，即 private final char[] value;</li>
<li>Java 9做了改进，采用 byte[] 数组来保存字符，即 private final byte[] value;</li>
</ul>
<p>之所以要把 String类设计为不可变类，主要是处于安全和性能的考虑，可归纳为如下4点。</p>
<ul>
<li>由于字符串无论在任何Java 系统中都广泛使用，会用来存储敏感信息，如账号，密码，网络路径，文件处理等场景里，保证字符串String类的安全性就尤为重要了，如果字符串是可变的，容易被篡改，那我们就无法保证使用字符串进行操作时，它是安全的，很有可能出现SQL注入，访问危险文件等操作。</li>
<li>在多线程中，只有不变的对象和值是线程安全的，可以在多个线程中共享数据。由于String天然的不可变，当一个线程修改了字符串的值，只会产生一个新的字符串对象，不会对其它线程的访问产生副作用，访问的都是同样的字符串数据，不需要任何同步操作。</li>
<li>字符串作为基础的数据结构，大量地应用在一些集合容器之中，尤其是一些散列集合，在散列集合中，存放元素都要根据对象的hashCode（）方法来确定元素的位置。由于字符串hashCode属性不会变更，保证了唯一性，使得类似 HashMap ,HashSet 等容器才能hi先相应的缓存功能。由于String 的不可变，避免重复计算 hashcode ，只要使用缓存的 hashcode，即可，这样一来大大提高了在散列集合中使用String对象的性能。</li>
<li>当字符串不可变时，字符串常量池才有意义。字符串常量池的出现，可以减少创建相同字面量的字符串，让不同的引用指向池中的同一个字符串，为运行时节约很多的堆内存。若字符串可变，字符串常量池失去意义，基于常量池的 String.intern() 方法也失效，每次创建新的字符串将在堆内开辟出新的空间，占据更多内存。</li>
</ul>
</div></div>
</li>
<li><p>说一说StringBuffer和StringBuilder有什么区别</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>StringBuffer 、 StringBuilder都代表可变的字符串对象，它们有共同的父类 AbstractStringBuilder ，并且两个类的构造方法和成员方法也基本相同。不同的是，StringBuffer是线程安全的，而StringBuilder是非线程安全的，(任何无状态的单例都是线程安全的，所以在Spring中使用StringBuilder)，所以StringBuilder性能略高，一般情况下，要创建一个内容可变的字符串，建议优先考虑StringBuilder</p>
<ul>
<li>append()</li>
<li>insert()</li>
<li>reverse()</li>
<li>setCharAt()</li>
<li>setLength()</li>
<li>toString()</li>
</ul>
</div></div>
</li>
<li><p>说一说你对字符串拼接的理解</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<ul>
<li><code>+</code> 运算符： 如果拼接的都是字符串字面量，则适合使用 + 运算符实现拼接</li>
<li>StringBuilder： 如果拼接的字符串包含变量，并不要求线程安全，则适合使用StringBilder</li>
<li>StringBuffer： 如果拼接的字符串包含变狼，并且要求线程安全，则适合使用StringBuffer</li>
<li>String类的concat方法：如果只是对两个字符串进行拼接，并且包含变量，则适合使用concat方法</li>
</ul>
</div></div>
</li>
<li><p>接口和抽象类有什么区别？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>从设计目的上来说，二者有如下的区别：</p>
<p>接口体现的是一种规范。对于接口的实现者而言，接口规定了实现者必须向外提供那些服务；对于接口的调用者而言，接口规定了调用者可以调用那些服务，以及如何调用这些服务。当在一个程序中使用接口时，接口是多个模块间的耦合标准；当在多个应用程序之间使用接口时，接口是多个程序之间的通信标准。</p>
<p>抽象类体现的是一种模板式设计。抽象类作为多个子类的抽象父类，可以被当作系统实现过程中的中间产品，这个中间产品已经实现了系统的部分功能，但这个产品依然不能当成最终产品，必须有更进一步的完善，这种完善可能有几种不同方式。</p>
<p>从使用方式上来说，二者有如下的区别：</p>
<ul>
<li>接口里只能包含抽象方法、静态方法（有实现）、默认方法（有实现）和私有方法（JDK8以上版本）、普通方法（不写修饰符默认就是public，default方法必须用default 修饰，只有在接口中有此特性）；抽象类和普通方法的区别仅仅是使用 abstract 修饰， 抽象类可以没有抽象方法。</li>
<li>接口里只能定义静态常量，不能定义普通成员变量，即使不用static 关键字也是静态常量；抽象类和普通类一致；</li>
<li>接口里不包含构造器；抽象类里虽然也有构造器，但抽象类里的构造器并不是用于创建对象，而是让其子类调用这些构造器来完成属于抽象类的初始化操作。</li>
<li>接口里不能包含初始化块</li>
<li>一个类最多只能有一个直接父类，包括抽象类；但一个类可以实现多个接口，通过实现多个接口可以弥补Java单继承的不足</li>
<li>接口里的内部类只能定义内部接口和枚举</li>
</ul>
<p>接口和抽象类很像，它们都具有如下共同的特征：</p>
<ul>
<li>接口和抽象类都不能实例化，它们都位于继承树的顶端，用于被其它类实现和继承。</li>
<li>接口和抽象类都可以包含抽象方法，实现接口或继承抽象类的普通子类都必须实现这些抽象方法。</li>
</ul>
<p>面向接口编程，降低程序的耦合</p>
</div></div>
</li>
<li><p>如何处理异常？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>在Java中，可以按照如下三个步骤处理异常：</p>
<ol>
<li><p>捕获异常</p>
<p>将业务异常包裹在 try 块内部，当业务代码中发生任何异常时，系统都会为此异常创建一个异常对象。创建异常对象之后，JVM会在 try 块之后寻找可以处理它的 catch 块，并将异常对象交给这个 catch 块处理。</p>
</li>
<li><p>在 catch 块中处理异常时，应该先记录日志，便于以后追溯这个异常。然后根据异常的类型、结合当前的业务情况，进行相应的处理。比如，给变量赋予一个新的默认值、直接返回空值、向外抛出一个自定义的异常交给调用者处理，等等。</p>
</li>
<li><p>回收资源</p>
<p>如果业务代码打开了某个资源，比如数据库连接、网络连接、磁盘文件等，则需要在这段业务代码执行完毕后关闭这项资源。并且，无论是否发生异常，都要尝试关闭这项资源。将关闭资源的代码写在finally块内。</p>
</li>
</ol>
</div></div>
</li>
<li><p>说一说Java 的异常机制</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>在Java中，可以按照如下三个步骤处理异常：</p>
<ol>
<li><p>捕获异常</p>
<p>将业务异常包裹在 try 块内部，当业务代码中发生任何异常时，系统都会为此异常创建一个异常对象。创建异常对象之后，JVM会在 try 块之后寻找可以处理它的 catch 块，并将异常对象交给这个 catch 块处理。</p>
</li>
<li><p>处理异常</p>
<p>在 catch 块中处理异常时，应该先记录日志，便于以后追溯这个异常。然后根据异常的类型、结合当前的业务情况，进行相应的处理。比如，给变量赋予一个新的默认值、直接返回空值、向外抛出一个自定义的异常交给调用者处理，等等。</p>
</li>
<li><p>回收资源</p>
<p>如果业务代码打开了某个资源，比如数据库连接、网络连接、磁盘文件等，则需要在这段业务代码执行完毕后关闭这项资源。并且，无论是否发生异常，都要尝试关闭这项资源。将关闭资源的代码写在finally块内。</p>
</li>
</ol>
</div></div>
</li>
<li><p>Java的异常机制</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<ol>
<li><p>关于异常处理</p>
<p>在Java中，处理异常的语句由 try 、 catch 、finally 三部分组成。其中，try 块用于包裹业务代码，catch块用于处理某个类型的异常，finally块则用于回收资源。当业务代码发生异常时，系统会创建一个异常对象，然后由 JVM 寻找可以处理这个异常的 catch 块，并将异常对象交给这个catch 块去处理。若异常代码打开了某项资源，则可以在finally块中关闭这项资源，因为无论是否发生异常，finally块一定会执行。</p>
</li>
<li><p>关于抛出异常</p>
<p>当程序出现错误时，系统会自动抛出异常。除此之外，Java也允许程序主动抛出异常。当业务代码中，判断某项错误的条件成立时，可以使用 throw 关键字向外抛出异常。在这种情况下，如果当前方法不知道如何处理这个异常，可以在方法签名上通过 throws 关键字声明抛出异常，则该异常将交给调用者处理。</p>
</li>
<li><p>关于异常跟踪栈</p>
<p>程序运行时，经常会发生一系列的方法调用，从而形成方法调用栈。异常机制会导致异常在这些方法之间传播，而异常传播的顺序和方法的调用相反。异常从发生异常的方法向外传播，首先传给该方法的调用者，再传给上层调用者，以此类推。最终会传到 main 方法，若依然没有得到处理，则JVM会终止程序，并打印异常跟踪栈的信息。</p>
</li>
</ol>
</div></div>
</li>
<li><p>说一说你对static关键字的理解</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>在Java类中只能包含成员变量、成员方法、构造器、初始化块、内部类（包括接口、枚举）5种成员，而static可以修饰成员变量、成员方法、初始化块、内部类（包括接口、枚举），以static修饰的成员就是类成员。类成员属于整个类，而不属于单个对象。</p>
<p>对于static关键字而言，有一条非常重要的规则：类成员（包括成员变量、方法、初始化块、内部类和枚举）不能访问实例成员（包括成员变量、方法、初始化块、内部类和内部枚举类）。因为类成员是属于类的，类成员的作用域比实例成员的作用域更大，完全可能出现类成员已经初始化完成，但实例成员还不曾实例化的情况。</p>
</div></div>
</li>
<li><p>static 和 final 有什么区别？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>static关键字可以修饰成员变量、成员方法、初始化块、内部类（包括接口、枚举），被static 修饰的成员是类的成员，它属于类，不属于单个对象。以下是static修饰这4种成员时表现得特征：</p>
<ul>
<li>类变量：被static修饰的成员变量叫做类变量（静态变量）。类变量属于类，它随类的信息存储在方法区，并不随对象存储在堆中，类变量可以通过类名来访问，也可以通过对象名来访问，但建议通过类名访问它</li>
<li>类方法：被static修饰的成员方法叫做类方法（静态方法）。类方法属于类，可以通过类名访问，也可以通过对象名访问，建议通过类名访问它。被static修饰的方法不能被重写。</li>
<li>静态块：被static修饰的初始化块叫静态初始化块。静态块属于类，它在类加载的时候被隐式调用一次，之后并不会再调用了。</li>
<li>静态内部类：被static修饰的内部类叫做静态内部类。静态内部类可以包含的内容和普通类一致。静态内部类不能访问外部类的实例成员，只能访问外部类的类成员。外部类的所有方法，初始化块都能访问其内部定义的静态内部类。</li>
</ul>
<p>final 关键字可以修饰类、方法、变量，以下是final修饰这3种目标时表现出来的特征：</p>
<ul>
<li>final类：final关键字修饰的类不能被继承</li>
<li>final方法：final关键字修饰的方法不能被重写</li>
<li>final变量：final关键字修饰变量，一旦获得了初始值，就不可以更改。</li>
</ul>
<p><strong>扩展</strong></p>
<p>变量分为成员变量、局部变量。</p>
<p>final修饰成员变量：</p>
<ul>
<li>类变量：可以在声明时指定初始值，也可以在静态初始化块中指定初始值；</li>
<li>实例变量：可以在声明时指定初始值，也可以在初始化块或构造方法中指定初始值；</li>
</ul>
<p>final修饰局部变量：</p>
<ul>
<li>可以在声明变量时指定初始值，也可以在后面的代码中指定初始值。</li>
</ul>
<p>注意：被 final修饰的任何形式的变量，一旦获得了初始值，就不可以被修改</p>
</div></div>
</li>
<li><p>说一说你对泛型的理解</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>从Java 5开始，Java引入了”参数化类型“的概念，允许程序在创建集合时指定集合元素的类型，Java的参数化类型被称为泛型（Generic）。例如 <code>List&lt;String&gt;</code>，表明该List只能保存字符串类型的对象。</p>
<p>有了泛型之后，避免了集合中的ClassCastException 异常</p>
</div></div>
</li>
<li><p>介绍一下泛型擦除</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>当把一个具有泛型信息的对象赋给另一个没有泛型信息的变量时，所有在尖括号之间的类型信息都将被扔掉。比如一个<code>List&lt;String&gt;</code>类型被转换为List，则该List对集合元素的类型检查变成了泛型参数的上限（即 Object）</p>
<p>上述规则即为泛型擦除</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        List&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        list.add(<span class="string">&quot;wkq&quot;</span>);</span><br><span class="line">        List list1 = list;</span><br><span class="line">        List&lt;Integer&gt; list2 = list1;</span><br><span class="line">        list2.add(<span class="number">123</span>);</span><br><span class="line"><span class="comment">//        List&lt;Object&gt; list3 = list;//泛型不支持型变</span></span><br><span class="line">        Integer[] integers = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>&#125;;</span><br><span class="line">        Number[] numbers = integers;<span class="comment">//数组支持型变</span></span><br><span class="line">        System.out.println(list.get(<span class="number">0</span>));</span><br><span class="line">        System.out.println(list1.get(<span class="number">0</span>));</span><br><span class="line">        System.out.println(list2.get(<span class="number">0</span>));</span><br><span class="line"><span class="comment">//        Integer integer = list2.get(0);//泛型不支持型变，但无状态的泛型支持型变 这里会报 ClassCastException</span></span><br><span class="line"><span class="comment">//        System.out.println(integer);</span></span><br><span class="line">        System.out.println(list.get(<span class="number">0</span>) <span class="keyword">instanceof</span> String);</span><br><span class="line">        System.out.println(list1.get(<span class="number">0</span>) <span class="keyword">instanceof</span> String);</span><br><span class="line">        System.out.println(list2.get(<span class="number">1</span>) <span class="keyword">instanceof</span> Integer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>数组和泛型有所不同，假设 Foo 是 Bar 的一个子类型（子类或者子接口），那么Foo[] 依然是Bar[] 的子类型，但<code>List&lt;Foo&gt;</code>不是 <code>List&lt;Bar&gt;</code>的子类型。Foo[] 自动向上转型 为 Bar[] 的方式称为型变，也就是说，Java的数组支持型变，但Java集合不支持型变。Java泛型的设计原则是，只要代码在编译时没有出现警告，就不会遇到运行时ClassCastException</p>
</div></div>
</li>
<li><p>List&lt;? super T&gt; 和 List&lt;? extends T&gt; 有什么区别？</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<ul>
<li>？ 是类型通配符，List &lt;?&gt; 可以表示各种泛型List的父类，意思是元素类型未知的List；</li>
<li>List&lt;? super T&gt; 用于设定类型通配符的下限，此处 ？ 代表一个未知的类型，但它必须是类型 T 的父类型;</li>
<li>List&lt;? extends T&gt;用于设定类型通配符的上限，此处 ？ 代表一个未知的类型，但它必须是类型T的子类型</li>
</ul>
</div></div>
</li>
<li><p>说一说你对Java反射机制的理解</p>
<div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案
    </button><div class="hide-content"><p><strong>参考答案</strong></p>
<p>Java程序中的对象在运行时可以表现为两种类型，即编译时类型和运行时类型。例如 Person p = new Student(); ，这行代码将会生成一个 p 变量，该变量的编译时类型为 Person，运行时类型为 Student。</p>
<p>有时，程序在运行时接收到外部传入的一个对象，该对象的编译时类型是Object，但程序又需要调用该对象的运行时类型的方法。这就要求程序需要在运行时发现对象和类的真实信息，而解决这个问题有以下两种做法：</p>
<ul>
<li>第一种做法是假设在编译时和运行时都完全知道类型的具体信息，在这种情况下，可以先使用 instanceof 运算符进行判断 ，再利用强制类型转换将其转换成运行时类型的变量即可。</li>
<li>第二种做法是编译时根本无法预知该对象和类可能属于那些类，程序只能依靠运行时信息来发现该对象和类的真实信息，这就必须使用反射。</li>
</ul>
<p>具体来说，通过反射机制，我们可以实现如下的操作：</p>
<ul>
<li>程序运行时，可以通过反射获得任意一个类的 Class 对象，并通过这个对象查看这个类的信息；</li>
<li>程序运行时，可以通过反射创建任意一个类的实例，并访问该实例的成员；</li>
<li>程序运行时，可以通过反射机制生成一个类的动态代理类或动态代理对象；</li>
</ul>
</div></div>
</li>
<li></li>
</ol>
<p>​    </p>
<p>​        </p>
</article><div class="tag_share"><div class="post-meta__tag-list"></div><div class="post_share"><div class="social-share" data-image="/cover/Java.png" data-sites="wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js" defer></script></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="/media/avatar.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">王开琦</div><div class="author-info__description">今日事今日毕</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">15</div></a></div><div class="card-info-data-item is-center"><a href="/tags/"><div class="headline">标签</div><div class="length-num">17</div></a></div><div class="card-info-data-item is-center"><a href="/categories/"><div class="headline">分类</div><div class="length-num">15</div></a></div></div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/blog/3-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9B%91%E6%8E%A7%E4%B8%8E%E8%B0%83%E4%BC%98-%E7%89%B9%E5%AE%9A%E8%AF%AD%E5%8F%A5%E7%9A%84%E5%8E%9F%E7%90%86%E5%92%8C%E8%B0%83%E4%BC%98/" title="3.数据库-数据库监控与调优-特定语句的原理和调优"><img src= "" data-lazy-src="/media/top_img.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="3.数据库-数据库监控与调优-特定语句的原理和调优"/></a><div class="content"><a class="title" href="/blog/3-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9B%91%E6%8E%A7%E4%B8%8E%E8%B0%83%E4%BC%98-%E7%89%B9%E5%AE%9A%E8%AF%AD%E5%8F%A5%E7%9A%84%E5%8E%9F%E7%90%86%E5%92%8C%E8%B0%83%E4%BC%98/" title="3.数据库-数据库监控与调优-特定语句的原理和调优">3.数据库-数据库监控与调优-特定语句的原理和调优</a><time datetime="2022-04-22T08:14:26.000Z" title="发表于 2022-04-22 16:14:26">2022-04-22</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/3-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9B%91%E6%8E%A7%E4%B8%8E%E8%B0%83%E4%BC%98-%E6%95%B0%E6%8D%AE%E5%BA%93%E8%B0%83%E4%BC%98%E7%90%86%E8%AE%BA/" title="数据库调优理论"><img src= "" data-lazy-src="/media/top_img.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="数据库调优理论"/></a><div class="content"><a class="title" href="/blog/3-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9B%91%E6%8E%A7%E4%B8%8E%E8%B0%83%E4%BC%98-%E6%95%B0%E6%8D%AE%E5%BA%93%E8%B0%83%E4%BC%98%E7%90%86%E8%AE%BA/" title="数据库调优理论">数据库调优理论</a><time datetime="2022-04-22T08:13:31.000Z" title="发表于 2022-04-22 16:13:31">2022-04-22</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/3-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9B%91%E6%8E%A7%E4%B8%8E%E8%B0%83%E4%BC%98-%E6%85%A2%E6%9F%A5%E8%AF%A2%E5%8F%91%E7%8E%B0%E4%B8%8E%E5%88%86%E6%9E%90/" title="慢查询发现与分析"><img src= "" data-lazy-src="/media/top_img.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="慢查询发现与分析"/></a><div class="content"><a class="title" href="/blog/3-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9B%91%E6%8E%A7%E4%B8%8E%E8%B0%83%E4%BC%98-%E6%85%A2%E6%9F%A5%E8%AF%A2%E5%8F%91%E7%8E%B0%E4%B8%8E%E5%88%86%E6%9E%90/" title="慢查询发现与分析">慢查询发现与分析</a><time datetime="2022-04-22T08:12:32.000Z" title="发表于 2022-04-22 16:12:32">2022-04-22</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/1-Java-JVM%E8%B0%83%E4%BC%98%E7%90%86%E8%AE%BA/" title="JVM 调优理论"><img src= "" data-lazy-src="/media/top_img.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="JVM 调优理论"/></a><div class="content"><a class="title" href="/blog/1-Java-JVM%E8%B0%83%E4%BC%98%E7%90%86%E8%AE%BA/" title="JVM 调优理论">JVM 调优理论</a><time datetime="2022-04-21T06:40:41.000Z" title="发表于 2022-04-21 14:40:41">2022-04-21</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/20-%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84-%E6%9C%8D%E5%8A%A1%E6%B2%BB%E7%90%86-%E6%9C%8D%E5%8A%A1%E6%B2%BB%E7%90%86Eureka/" title="服务治理Eureka"><img src= "" data-lazy-src="/media/top_img.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="服务治理Eureka"/></a><div class="content"><a class="title" href="/blog/20-%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84-%E6%9C%8D%E5%8A%A1%E6%B2%BB%E7%90%86-%E6%9C%8D%E5%8A%A1%E6%B2%BB%E7%90%86Eureka/" title="服务治理Eureka">服务治理Eureka</a><time datetime="2022-04-13T13:18:27.000Z" title="发表于 2022-04-13 21:18:27">2022-04-13</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="footer_custom_text">Copyright© 2022 blog.wkq.pub <span>陇ICP备2021003596号</span></a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="local-search"><div class="search-dialog"><div class="search-dialog__title" id="local-search-title">本地搜索</div><div id="local-input-panel"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div></div><hr/><div id="local-search-results"></div><span class="search-close-button"><i class="fas fa-times"></i></span></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="/js/search/local-search.js"></script><script>var preloader = {
  endLoading: () => {
    document.body.style.overflow = 'auto';
    document.getElementById('loading-box').classList.add("loaded")
  },
  initLoading: () => {
    document.body.style.overflow = '';
    document.getElementById('loading-box').classList.remove("loaded")

  }
}
window.addEventListener('load',preloader.endLoading())</script><div class="js-pjax"><script>if (document.getElementsByClassName('mermaid').length) {
  if (window.mermaidJsLoad) mermaid.init()
  else {
    getScript('https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js').then(() => {
      window.mermaidJsLoad = true
      mermaid.initialize({
        theme: 'default',
      })
      true && mermaid.init()
    })
  }
}</script></div><div class="aplayer no-destroy" data-id="7675104902" data-server="tencent" data-type="playlist" data-fixed="true" data-mini="true" data-listFolded="false" data-order="random" data-preload="none" data-autoplay="true" muted></div><canvas class="fireworks" mobile="true"></canvas><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/fireworks.min.js"></script><script defer="defer" id="fluttering_ribbon" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-fluttering-ribbon.min.js"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js"></script><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>let pjaxSelectors = [
  'title',
  '#config-diff',
  '#body-wrap',
  '#rightside-config-hide',
  '#rightside-config-show',
  '.js-pjax'
]

if (false) {
  pjaxSelectors.unshift('meta[property="og:image"]', 'meta[property="og:title"]', 'meta[property="og:url"]')
}

var pjax = new Pjax({
  elements: 'a:not([target="_blank"])',
  selectors: pjaxSelectors,
  cacheBust: false,
  analytics: false,
  scrollRestoration: false
})

document.addEventListener('pjax:send', function () {

  // removeEventListener scroll 
  window.removeEventListener('scroll', window.tocScrollFn)
  window.removeEventListener('scroll', scrollCollect)

  typeof preloader === 'object' && preloader.initLoading()
  
  if (window.aplayers) {
    for (let i = 0; i < window.aplayers.length; i++) {
      if (!window.aplayers[i].options.fixed) {
        window.aplayers[i].destroy()
      }
    }
  }

  typeof typed === 'object' && typed.destroy()

  //reset readmode
  const $bodyClassList = document.body.classList
  $bodyClassList.contains('read-mode') && $bodyClassList.remove('read-mode')

})

document.addEventListener('pjax:complete', function () {
  window.refreshFn()

  document.querySelectorAll('script[data-pjax]').forEach(item => {
    const newScript = document.createElement('script')
    const content = item.text || item.textContent || item.innerHTML || ""
    Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
    newScript.appendChild(document.createTextNode(content))
    item.parentNode.replaceChild(newScript, item)
  })

  GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()

  typeof chatBtnFn === 'function' && chatBtnFn()
  typeof panguInit === 'function' && panguInit()

  // google analytics
  typeof gtag === 'function' && gtag('config', '', {'page_path': window.location.pathname});

  // baidu analytics
  typeof _hmt === 'object' && _hmt.push(['_trackPageview',window.location.pathname]);

  typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()

  // Analytics
  if (false) {
    MtaH5.pgv()
  }

  // prismjs
  typeof Prism === 'object' && Prism.highlightAll()

  typeof preloader === 'object' && preloader.endLoading()
})

document.addEventListener('pjax:error', (e) => {
  if (e.request.status === 404) {
    pjax.loadUrl('/404.html')
  }
})</script></div><script src="/live2d_models/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2d_models/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"/live2d_models/assets/penchan.model.json"},"display":{"position":"left","width":100,"height":150,"hOffset":-10,"vOffset":40},"mobile":{"show":true},"react":{"opacity":0.7},"log":false});</script></body></html>